/**
 * @author kangkai
 * 状态机， 
 * 0，自身id
 * 1,对自己的模型（rigidbody）,model3d
 * 2，对状态的管理（添加删除）
 * 3.运行、切换状态 
 * 4,向外部发送事件,On_FSMEvent
 * 
 * %，注意各个fsm的子类是可以互相注册事件的，但是最好一些重要的事情要通知主逻辑一下
 * //-----------------Exp---------------
 * 	9,关于状态机，函数的定义放在主的FSM里(便于管理)，具体什么时候用是由各个状态去执行的，就是把函数的声明和使用分开处理即可
 * *10，经验就是一个fsm控制另一个fsm的生成，销毁或是状态变化的时候，要通过中介者GamePlay来通讯，
 *	这个是有用的，因为他涉及的跨fsm的调用，一个fsm请求去改变另一个fsm的状态,或控制另一个fsm对象的生成和销毁
 * 
 * 注意stateA和stateM的状态可以重复使用StateID,比如-1就通用
 * 记得如果死亡的时候是要搞掉2个状态的
 * 
1,fsm做了整理，发现其实fsm之间是可以通信的。并且好处有很多啊。
	现在的结构是支持在fsmM里的fsm 去查询其他fsm状态的,但是需要保证之读而不写
	fsm之间是可以查询但禁止直接操作的,fsm操作的时间要发送到总控逻辑来处理的

4,新的发现是：结构不是特别要求是最好的，保证能通信的对象都能通到信就可
 * 
 * ----------------Log----------------
 * --1207
 * 1,增加配合物理引擎使用的
 * 
 * 2，做出更通用的结构，因为实际发现fsm需要有自己的各个方法的，
 * 	之所以需要被继承，继承的fsm里可以有自己的工具函数（供自己的state使用的）,子类要有自己的各个属性，md3d,body的各个零件的3d表示和phy表示
 * 	
 * 	3,简化了结构，做除了一个更强更清洁的结构
 * 	
 * 	如果要使用物理模型，则要把b2Body.userData=md3d,
 * 	在最后更新完物理引擎后再对每个md3d设置位置
 */
package kgame5.kengine.gameunit.parts.kfsm {
import kgame5.k3d.core.obj3d.hardvo.HardVO;
import kgame5.kengine.events.FSMEvent;
import kgame5.kengine.events.SendCommandEvent;
import kgame5.kutil.KEvent;



import flash.events.*;
import flash.utils.Dictionary;

public class FSM extends EventDispatcher{
	public static const 
		EVENT_FSM_EVENT:String="EVENT_FSM_EVENT";//fsm对外发送了通用事件
	public static const 
		EVENTTYPE_SWITCH_STATE:String="EVENTTYPE_SWITCH_STATE";//对外发出事件
	public static const 
		STATE_EMPTY:int=-1;//状态机的空白状态
	//___________________Property_____________________
	
	//--状态机内部的状态,因为比如坦克有移动和攻击两个并列的状态，所以要有2个状态,这个2个状态控制同一个，又互相有影响，所以做到一个
	private  var dict_states:Dictionary=null;//状态集合

	//--状态的使用
	protected var curState:GState=null;//当前的状态
	
	private var id:int;
	
	private var _vo:Object;//数据结构
	private var _hardVO:HardVO;//刚体数据
	
	//____________________Method__________________
	public function FSM(id:int){
		
		this.id=id;
		
		dict_states=new Dictionary();
		
		//默认有个空状态的,状态值是-1
		addState(new GState(STATE_EMPTY));
	}
	
	public function setVO(p_vo:Object):void{
		this._vo=p_vo;
	}
	
	public function setHardVO(hardVO:HardVO):void{
		this._hardVO=hardVO;
	}

	//这个很重要，被fsmM卸载的是要要释放内部资源
	public function dispose():void{}
	
	public function getID():int{
		return id;
	}

	//----对状态的管理,添加，删除，查找//
	public function addState(s:GState):void{
		dict_states[s.getID()]=s;
		
		s.setFSM(this);
	}
	
	public function findState(stateID:int):GState{
		return dict_states[stateID];
	}
	
	public function removeState(stateID:int):void{
		delete dict_states[stateID];
	}
	
	//取得当前的状态，这个挺有用的，用来判断当前的状态
	public function getCurState():GState{
		return curState;
	}
	
	//----状态的使用
	// 更新自己的状态
	public function update():void{
		if(curState!=null){
			curState.update();
		}
	}
	
	public function switchState(stateID:int,info:Object=null):void{
		if(curState!=null){
			//T.p("退出State:"+curState.getID());
			curState.exit();
		}
		var nextState:GState=findState(stateID);
		if(nextState!=null){
			curState=nextState;
			
			curState.setHardVO(_hardVO);
			curState.setVO(this._vo);
			
			//T.p("进入State:"+curState.getID());
			curState.enter(info);
			
			//--发送时间说自己切换了状态
			this.dispatchEvent(new KEvent(EVENTTYPE_SWITCH_STATE,stateID));
		}else{
			throw new Error("!!FSM.changeState,nextState=null "+stateID);
		}
	}
	
	//==================通知GUActor有事件=====================
	public function sendNotify(name:String,data:Object):void{
		this.dispatchEvent(new FSMEvent(name,data));
	}
	//==================通知GUActor对外发送command=====================
	public function sendCommand(commandName:String,data:Object):void{
		this.dispatchEvent(new SendCommandEvent(commandName,data));
	}
}//end of class
}